﻿

using System;
using System.Collections.Generic;
using System.Linq;

namespace Bzure.Common.AOP
{
    /// <summary>
    /// A weaver objects chain that will be populated dynamically runtime. This is a internal class that is used by DynamicAspect.
    /// </summary>
    class AspectChain : LinkedList<IAspect>
    {
        internal void BeforeMethodCall(WeavingContext context)
        {
            if(First ==null)
                return;

            var current = First;

            while(current !=null)
            {
                current.Value.OnBeforeMethodCall(context);
                current=current.Next;
            };
       }

        internal bool HasAroundMethod(WeavingContext context) 
        {
                return this.Any( a => a.HasArroundMethod(context));
        }

        internal void AroundMethodcall(WeavingContext context)
        {
            if (First == null)
                return;

            var current = First;

            while (current != null)
            {
                current.Value.OnAroundMethodCall(context);
                current = current.Next;
            };
        }

        internal bool ExceptionMethodCall(WeavingContext context, Exception ex)
        {
            if (First == null)
                return false;

            var current = First;

            while (current != null)
            {
                if (current.Value.OnExceptionMethodCall(context, ex))
                    return true;
                current = current.Next;
            };
            return false;
        }

        internal void AfterMethodCall(WeavingContext context)
        {
            if (Last != null)
            {
                var current = Last;
                while (current != null)
                {
                    current.Value.OnAfterMethodCall(context);
                    current = current.Previous;
                }
            }
        }

        internal void PropertyChanging(WeavingContext context)
        {
            if (First == null)
                return;

            var current = First;

            while (current != null)
            {
                current.Value.OnPropertyChanging(context);
                current = current.Next;
            };
        }

        internal void PropertyChanged(WeavingContext context)
        {
            if (Last != null)
            {
                var current = Last;
                while (current != null)
                {
                    current.Value.OnPropertyChanged(context);
                    current = current.Previous;
                }
            }
        }

        internal void BeforeGetValue(WeavingContext context)
        {
            if (First == null)
                return;

            var current = First;

            while (current != null)
            {
                current.Value.OnBeforeGetValue(context);
                current = current.Next;
            };
        }

        internal void AfterGetValue(WeavingContext context)
        {
            if (Last != null)
            {
                var current = Last;
                while (current != null)
                {
                    current.Value.OnAfterGetValue(context);
                    current = current.Previous;
                }
            }
        }
    }
}